package queue.impl;

import com.sun.org.apache.regexp.internal.RE;
import queue.BlockingQueue;
import queue.Delayed;

import java.util.PriorityQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author 老顾
 * @title: DelayQueue
 * @projectName java-restudy
 * @email: 1437594522@qq.com
 * @date 2022/11/4 20:04
 */
public class DelayQueue<E extends Delayed> implements BlockingQueue<E> {

    private final transient ReentrantLock lock = new ReentrantLock();
    private final PriorityQueue<E> q = new PriorityQueue<>();

    private final Condition available = lock.newCondition();

    @Override
    public boolean add(E e) {
        return offer(e);
    }

    @Override
    public boolean offer(E e) {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            q.offer(e);
            if (q.peek() == e) {
                available.signal();
            }
            return true;
        }finally {
            lock.unlock();
        }
    }

    @Override
    public E poll() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            E first = q.peek();
            if (first == null || first.getDelay(TimeUnit.NANOSECONDS)>0) {
                return null;
            }else {
                return q.poll();
            }
        }finally {
            lock.unlock();
        }
    }

    @Override
    public E peek() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            return q.peek();
        }finally {
            lock.unlock();
        }
    }
}
